package com.yanqu.road.server.gameplayer.module.activity.treasure;

import com.yanqu.road.entity.activity.ActivityDisperseGoldInfo;
import com.yanqu.road.entity.activity.ActivityDisperseGoldResult;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.treasure.TreasureActivityPlace;
import com.yanqu.road.entity.activity.treasure.TreasureGain;
import com.yanqu.road.entity.activity.treasure.TreasureResult;
import com.yanqu.road.entity.activity.treasure.UserTreasureActivityData;
import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogTreasureFind;
import com.yanqu.road.entity.task.args.HolidayActivityArgs;
import com.yanqu.road.logic.bussiness.player.UserTreasureBussiness;
import com.yanqu.road.pb.treasureactivity.TreasureActivityProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.DecorationModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.treasure.TreasureActivityMgr;
import com.yanqu.road.entity.activity.treasure.TreasurePlaceProgressInfo;
import com.yanqu.road.server.manger.config.GoodsBagMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.pb.TreasureActivityPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TreasureActivityModule extends GeneralModule {
    //activityId
    private Map<Integer, UserTreasureActivityData> userTreasureActivityDataMap;      //玩家数据

    public TreasureActivityModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        List<Integer> activityIdList = getActivityIdList();
        if (activityIdList.size() == 0) {
            userTreasureActivityDataMap = new ConcurrentHashMap<>();
        } else {
            userTreasureActivityDataMap = UserTreasureBussiness.getUserActivityDataMap(player.getUserId(), activityIdList);
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        for (UserTreasureActivityData userTreasureActivityData : userTreasureActivityDataMap.values()) {
            if (userTreasureActivityData.isInsertOption()) {
                UserTreasureBussiness.addUserTreasureActivityData(userTreasureActivityData);
            } else if (userTreasureActivityData.isUpdateOption()) {
                UserTreasureBussiness.updateUserTreasureActivityData(userTreasureActivityData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        syncActivity();
    }

    /**
     * 寻宝
     *
     * @param activityId
     * @param findType
     * @return
     */
    public TreasureResult findTreasure(int activityId, int findType) {
        TreasureResult result = new TreasureResult();

        if (findType != 1 && findType != 2) {
            result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_FIND_NUM_ERROR);
            return result;
        }

        ActivityInfo activityInfo = NormalActivityMgr.getActivityInfo(activityId);
        if (!checkActivity(activityInfo, result)) {
            return result;
        }

        UserTreasureActivityData userData = getUserActivityData(activityId);

        Property consume = new Property();
        int consumeGoodId = TreasureActivityMgr.getActivityConsumeId(activityInfo);
        int findTimes;
        if (1 == findType) {
            findTimes = 1;
            consume.setGood(consumeGoodId, BigInteger.ONE);
        } else {
            if (userData.getTaskProgress() == 0) {//没有获得过信物不能十连
                result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_FIND_NUM_ERROR);
                return result;
            }
            findTimes = 10;
            consume.setGood(consumeGoodId, BigInteger.valueOf(9L));   //消耗9个
        }

        //扣除消耗道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Activity, eLogMoneyType.TreasureFindUesGoods)) {
            result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_GOODS_NO_ENOUGH);
            return result;
        }

        //玩家活动数据
        result.setUserTreasureActivityData(userData);

        Property totalRewards = new Property();
        int totalToken = 0;
        //1次或10次
        for (int i = 0; i < findTimes; i++) {

            TreasureGain gain = findOne(userData, activityInfo);

            totalRewards.addProperty(gain.getRewards());

            totalToken += gain.getTokenNum();
            //行走步数
            result.getFindStepList().add(gain.getFindStep());
            //大地点
            if (gain.getPlaceId() != 0) {
                result.getPlaceIdList().add(gain.getPlaceId());
            }
        }
        //奖励
        player.getModule(CurrencyModule.class).addCurrency(totalRewards, eLogMoneyType.Activity, eLogMoneyType.TreasureFindReword);

        String logReward = PropertyHelper.parsePropertyToString(totalRewards);

        //成就
        player.notifyListener(eGamePlayerEventType.TreasureActivityProgress.getValue(), new HolidayActivityArgs(activityInfo.getChildType(), BigInteger.valueOf(userData.getTaskProgress())));
        player.notifyListener(eGamePlayerEventType.TreasureActivityScoreCrossRank.getValue(), new HolidayActivityArgs(activityInfo.getChildType(), BigInteger.valueOf(userData.getScore())));
        player.notifyListener(eGamePlayerEventType.TreasureActivityScoreRank.getValue(), new HolidayActivityArgs(activityInfo.getChildType(), BigInteger.valueOf(userData.getScore())));

        //加上信物奖励给客户端显示用
        totalRewards.addProperty(TreasureActivityMgr.getActivityTokenId(activityInfo),BigInteger.valueOf(totalToken));

        result.setRewards(PropertyHelper.parsePropertyToString(totalRewards));

        // 日志
        List<Integer> logStepList = new ArrayList<>(result.getFindStepList());
        List<Integer> logPlaceList = new ArrayList<>(result.getPlaceIdList());
        LogTreasureFind logTreasureFind = new LogTreasureFind(
                activityInfo.getActivityId(),
                getUserId(),
                findTimes,
                logStepList.stream().mapToInt(item -> item).sum(),
                logStepList,
                logPlaceList,
                logReward,
                userData.getRouteIndex()
        );
        LogMgr.addLogTreasureFind(logTreasureFind);

        return result;
    }


    /**
     * 寻宝一次
     *
     * @param userData
     * @param activityInfo
     * @return
     */
    public TreasureGain findOne(UserTreasureActivityData userData, ActivityInfo activityInfo) {
        TreasureGain result = new TreasureGain();
        try {
            int randomStep = TreasureActivityMgr.getRandomStepNum(activityInfo);

            TreasurePlaceProgressInfo placeInfo = TreasureActivityMgr.getPlaceInfo(userData.getActivityId(), userData.getRouteIndex() + randomStep);

            //步数 积分奖励
            long addScore = TreasureActivityMgr.getActivityStepScore(activityInfo) * randomStep;

            Property rewards = new Property(TreasureActivityMgr.getActivityScoreId(activityInfo), BigInteger.valueOf(addScore));
            result.getRewards().addProperty(rewards);

            //是否大地点
            if (placeInfo.getRoutProgress() == 0) {
                result.setPlaceId(placeInfo.getPlaceId());

                //宝箱奖励
                int rewardBox = placeInfo.getRewardBox();
                OpenGoodsBagResult openGoodsBagResult = GoodsBagMgr.getRandomGoods(rewardBox);
                if (openGoodsBagResult != null) {
                    //记录奖励
                    result.getRewards().addProperty(openGoodsBagResult.getReward());
                }
                //灵狐信物不进背包
                Property token = PropertyHelper.parseStringToProperty(placeInfo.getRewardToken());
                if (token != null) {
                    int tokenNum = token.getCountByGoodsId(TreasureActivityMgr.getActivityTokenId(activityInfo)).intValue();
                    userData.setTaskProgress(userData.getTaskProgress() + tokenNum);
                    result.setTokenNum(tokenNum);
                }
            }

            userData.setRouteIndex(userData.getRouteIndex() + randomStep);
            userData.setScore(userData.getScore() + addScore);
            result.setFindStep(randomStep);
            result.setRet(0);

        } catch (Exception e) {
            log.error("findOne", e);
        }
        return result;
    }

    /**
     * 领取圈数奖励
     *
     * @param activityId
     * @return
     */
    public TreasureResult getRoundReward(int activityId) {
        TreasureResult result = new TreasureResult();
        ActivityInfo activityInfo = NormalActivityMgr.getActivityInfo(activityId);

        if (!checkActivity(activityInfo, result)) {
            return result;
        }
        UserTreasureActivityData userActivityData = getUserActivityData(activityId);

        TreasurePlaceProgressInfo currentPlace = TreasureActivityMgr.getPlaceInfo(activityId, userActivityData.getRouteIndex());


        //不能领取
        if (currentPlace.getRound() == 0 || currentPlace.getRound() <= userActivityData.getRewardRound()) {
            result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_ROUND_REWARD_NO_FIND);
            return result;
        }

        //每圈信物奖励
        int tokenNum = TreasureActivityMgr.getActivityRoundTokenReward(activityInfo);
        int tokenId = TreasureActivityMgr.getActivityTokenId(activityInfo);
        userActivityData.setRewardRound(userActivityData.getRewardRound() + 1);
        userActivityData.setTaskProgress(userActivityData.getTaskProgress() + tokenNum);
        result.setUserTreasureActivityData(userActivityData);
        result.setRewards(PropertyHelper.parsePropertyToString(new Property(tokenId,BigInteger.valueOf(tokenNum))));
        //成就进度
        player.notifyListener(eGamePlayerEventType.TreasureActivityProgress.getValue(), new HolidayActivityArgs(activityInfo.getChildType(), BigInteger.valueOf(userActivityData.getTaskProgress())));

        return result;
    }

    private void syncUserDataList() {
        List<ActivityInfo> activityInfoList = getActivityInfoList();
        if (activityInfoList.size() > 0) {
            TreasureActivityProto.UserTreasureDataTempDataListMsg.Builder respMsg = TreasureActivityProto.UserTreasureDataTempDataListMsg.newBuilder();
            for (ActivityInfo activityInfo : activityInfoList) {
                if (!isTreasureSystemOpen(activityInfo)) continue; // 系统解锁判断
                UserTreasureActivityData userdata = getUserActivityData(activityInfo.getActivityId());
                TreasureActivityProto.UserTreasureDataTemp.Builder useDataTemp = TreasureActivityPb.parseUserDataTempBuilder(userdata,
                        TreasureActivityMgr.getUserDisperseGoldTimes(userdata),
                        TreasureActivityMgr.getPlaceInfo(activityInfo.getActivityId(), userdata.getRouteIndex()));
                respMsg.addUserTreasureData(useDataTemp);
                //同步成就数据
                player.notifyListener(eGamePlayerEventType.TreasureActivityProgress.getValue(), new HolidayActivityArgs(activityInfo.getChildType(), BigInteger.valueOf(userdata.getTaskProgress())));
            }
            player.sendPacket(ClientProtocol.U_ACTIVITY_TREASURE_USER_DATA, respMsg);
        }
    }

    /**
     * 活动用户数据
     *
     * @param activityId
     */
    private void syncUserDataList(int activityId) {
        TreasureActivityProto.UserTreasureDataTempDataListMsg.Builder respMsg = TreasureActivityProto.UserTreasureDataTempDataListMsg.newBuilder();
        UserTreasureActivityData userdata = getUserActivityData(activityId);
        TreasureActivityProto.UserTreasureDataTemp.Builder useDataTemp = TreasureActivityPb.parseUserDataTempBuilder(userdata,
                TreasureActivityMgr.getUserDisperseGoldTimes(userdata),
                TreasureActivityMgr.getPlaceInfo(activityId, userdata.getRouteIndex()));
        respMsg.addUserTreasureData(useDataTemp);
        player.sendPacket(ClientProtocol.U_ACTIVITY_TREASURE_USER_DATA, respMsg);
    }

    /**
     * 活动地点配置
     */
    private void syncPlaceConfigList() {
        Map<Integer, List<TreasureActivityPlace>> map = TreasureActivityMgr.getPlaceMapConfig();
        if (map.size() > 0) {
            TreasureActivityProto.TreasurePlaceConfigListMsg.Builder respMsg = TreasureActivityProto.TreasurePlaceConfigListMsg.newBuilder();
            for (Map.Entry<Integer, List<TreasureActivityPlace>> dataEntry : map.entrySet()) {
                TreasureActivityProto.TreasurePlaceConfig.Builder placeConfigMsg = TreasureActivityPb.parsePlaceConfigMsg(dataEntry.getKey(), dataEntry.getValue(),player.getLanguage());
                respMsg.addTreasurePlaceConfig(placeConfigMsg);
            }
            player.sendPacket(ClientProtocol.U_ACTIVITY_TREASURE_PLACE_DATA, respMsg);
        }
    }

    /**
     * 自动将活动道具转为活动积分
     *
     * @param activityInfoList
     */
    public void autoUseActivityGoods(List<ActivityInfo> activityInfoList) {
        if (null != activityInfoList && activityInfoList.size() > 0) {
            for (ActivityInfo activityInfo : activityInfoList) {
                autoUseActivityGoods(activityInfo);
            }
        }
    }

    public void autoUseActivityGoods(ActivityInfo activityInfo) {
        if (ActivityMgr.activityInShowPeriod(activityInfo) || ActivityMgr.activityInRewardPeriod(activityInfo)) {//在展示期或者领奖期
            int activityConsumeId = TreasureActivityMgr.getActivityConsumeId(activityInfo);
         //   player.getModule(BagModule.class).removeActivityBagItemToScore(activityInfo, TreasureActivityMgr.getActivityScoreId(activityInfo), activityConsumeId, 0, MailManager.TREASURE_ACTIVITY_GOODS_AUTO_CONSUME_TITLE, MailManager.TREASURE_ACTIVITY_GOODS_AUTO_CONSUME_CONTENT);
        }
    }


    public List<Integer> getActivityIdList() {
        List<Integer> activityIdList = new ArrayList<>();
        List<ActivityInfo> activityInfoList = getActivityInfoList();
        for (ActivityInfo activityInfo : activityInfoList) {
            activityIdList.add(activityInfo.getActivityId());
        }
        return activityIdList;
    }

    public List<ActivityInfo> getActivityInfoList() {
        return NormalActivityMgr.getOpenActivityInfoList(eActivityType.TreasureActivity.getValue());
    }

    public UserTreasureActivityData getUserActivityData(int activityId) {
        UserTreasureActivityData userTreasureActivityData = userTreasureActivityDataMap.get(activityId);
        if (userTreasureActivityData == null) {
            synchronized (userTreasureActivityDataMap) {
                userTreasureActivityData = userTreasureActivityDataMap.get(activityId);
                if (userTreasureActivityData == null) {
                    userTreasureActivityData = new UserTreasureActivityData();
                    userTreasureActivityData.setInsertOption();
                    userTreasureActivityData.setUserId(player.getUserId());
                    userTreasureActivityData.setActivityId(activityId);
                    userTreasureActivityData.setRouteIndex(1); //初始化起点
                    userTreasureActivityDataMap.put(activityId, userTreasureActivityData);
                }
            }
        }
        return userTreasureActivityData;
    }

    /**
     * 活动送财
     *
     * @param activityInfo
     * @return
     */
    public ActivityDisperseGoldResult disperseGold(ActivityInfo activityInfo, String manifesto) {
        ActivityDisperseGoldResult result = new ActivityDisperseGoldResult();
        UserTreasureActivityData userTreasureActivityData = getUserActivityData(activityInfo.getActivityId());

        if (TreasureActivityMgr.getUserDisperseGoldTimes(userTreasureActivityData, activityInfo) <= 0) {
            result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_GOLD_TIMES_NO_ENOUGH);         //次数不足
            return result;
        }
        List<String> goldParam = TreasureActivityMgr.getActivityGoldParam(activityInfo);
        if (userTreasureActivityData.getScore() < Long.valueOf(goldParam.get(0))) {
            result.setRet(GameErrorCode.E_ACTIVITY_TREASURE_SCORE_NO_ENOUGH);             //活动积分不足
            return result;
        }


        userTreasureActivityData.setUseTimes(userTreasureActivityData.getUseTimes() + 1);

        syncUserDataList(activityInfo.getActivityId());

        List<Integer> decorationIdList = player.getModule(DecorationModule.class).getDecorationIdList(eDecorationType.HonoraryTitle.getValue());
        ActivityDisperseGoldInfo goldInfo = new ActivityDisperseGoldInfo();
        goldInfo.setActivityId(activityInfo.getActivityId());
        goldInfo.setType(activityInfo.getType());
        goldInfo.setUserId(player.getUserId());
        goldInfo.setManifesto(manifesto);
        goldInfo.setBeginTime(System.currentTimeMillis());
        goldInfo.setHonoraryTitles(StringUtils.listToString(decorationIdList, ","));
        if (NormalActivityMgr.hasConditionType(activityInfo.getActivityId(), eGamePlayerEventType.TreasureActivityScoreCrossRank.getValue())) {
            goldInfo.setServerList(activityInfo.getServerIdList());
        } else {
            List<Long> serverList = new ArrayList<>();
            serverList.add(GameServer.getInstance().getServerId());
            goldInfo.setServerList(serverList);
        }
        goldInfo.setUserBaseInfo(UserMgr.getUserBaseInfo(player.getUserId(), GameServer.getInstance().getServerId()));
        result.setGoldInfo(goldInfo);
        return result;
    }

    /**
     * 系统解锁
     */
    public void initSystem() {
        syncUserDataList();
        syncPlaceConfigList();
        //autoUseActivityGoods(NormalActivityMgr.getOpenActivityInfoList(eActivityType.TreasureActivity.getValue()));
    }

    public void syncActivity() {
        syncUserDataList();
        syncPlaceConfigList();
        //autoUseActivityGoods(NormalActivityMgr.getOpenActivityInfoList(eActivityType.TreasureActivity.getValue()));
    }


    private boolean checkActivity(ActivityInfo activityInfo, TreasureResult result) {
        if (activityInfo == null || activityInfo.getType() != eActivityType.TreasureActivity.getValue()) {
            result.setRet(GameErrorCode.E_ACTIVITY_NO_FOUND);
            return false;
        }
        if (!isTreasureSystemOpen(activityInfo)) {
            result.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
            return false;
        }
        if (!ActivityMgr.activityInTime(activityInfo)) {
            result.setRet(GameErrorCode.E_ACTIVITY_OVER_TIME);
            return false;
        }
        return true;
    }

    public boolean isTreasureSystemOpen(ActivityInfo info) {
        if (info == null || info.getType() != eActivityType.TreasureActivity.getValue()) {
            return false;
        }
        if (info.getChildType() == 1 && SystemOpenMgr.systemOpen(player, eSystemId.TreasureActivity.getValue())) {
            return true;
        } else if (info.getChildType() == 2 && SystemOpenMgr.systemOpen(player, eSystemId.GuiChuiDengActivity.getValue())) {
            return true;
        }
        return false;
    }
}
